package cn.qiuxiang.react.amap3d;

import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.geocoder.BusinessArea;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;


import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.DriveStep;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RideStep;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkRouteResult;
import com.amap.api.services.route.WalkStep;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@SuppressWarnings("unused")
public class AMapGeoSearchModule extends ReactContextBaseJavaModule implements PoiSearch.OnPoiSearchListener, GeocodeSearch.OnGeocodeSearchListener {
    private ReactApplicationContext reactContext;
    private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
    AMapGeoSearchModule(ReactApplicationContext reactContext) {
        super(reactContext);

        this.reactContext = reactContext;
    }
    @Override
    public String getName() {
        return "AMapGeoSearch";
    }
    @Override
    public void onPoiSearched(PoiResult poiResult, int resultCode)
    {
        if (resultCode == AMapException.CODE_AMAP_SUCCESS) {

            ArrayList<PoiItem>  pois =poiResult.getPois();
            WritableArray array = Arguments.createArray();
            for(int i = 0;i < pois.size(); i ++) {

                PoiItem item = pois.get(i);
                WritableMap map = Arguments.createMap();
                map.putDouble("latitude", item.getLatLonPoint().getLatitude());
                map.putDouble("longitude", item.getLatLonPoint().getLongitude());
                map.putString("name", item.getTitle());
                map.putString("address",item.getSnippet());
                map.putString("city",item.getCityName());
                map.putString("citycode",item.getCityCode());
                map.putString("adcode",item.getAdCode());
                array.pushMap(map);
            }

            eventEmitter.emit("AMapGeoSearch",array);
        }
    }
    @Override
    public void onPoiItemSearched(PoiItem var1, int var2)
    {

    }
    @ReactMethod
    public void init(String key, Promise promise) {

        eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
        promise.resolve(null);
    }

    @ReactMethod
    public void searchPOI(final ReadableMap param)
    {

        double lat = param.getDouble("latitude");
        double lng = param.getDouble("longitude");
        double radius = param.getDouble("radius");
        String searchKey = param.getString("searchKey");
        int currentPage = 0;
        PoiSearch.Query query = new PoiSearch.Query(searchKey,  "", "");// 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query.setCityLimit(true);
        query.setPageSize(50);
        query.setPageNum(currentPage);
        LatLonPoint searchLatlonPoint = new LatLonPoint(lat, lng);
        if (searchLatlonPoint != null) {
            PoiSearch poiSearch = new PoiSearch(this.reactContext, query);
            poiSearch.setOnPoiSearchListener(this);
            poiSearch.setBound(new PoiSearch.SearchBound(searchLatlonPoint, (int)radius, true));//
            poiSearch.searchPOIAsyn();
        }
    }
    @ReactMethod
    public void searchPOIkeyWord(final ReadableMap param)
    {

        double lat = param.getDouble("latitude");
        double lng = param.getDouble("longitude");
        double radius = param.getDouble("radius");
        String searchKey = param.getString("searchKey");
        String city = param.getString("city");
        int currentPage = 0;
        PoiSearch.Query query = new PoiSearch.Query(searchKey,  "", city);// 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query.setCityLimit(true);
        query.setPageSize(50);
        query.setPageNum(currentPage);
        LatLonPoint searchLatlonPoint = new LatLonPoint(lat, lng);
        if (searchLatlonPoint != null) {
            PoiSearch poiSearch = new PoiSearch(this.reactContext, query);
            poiSearch.setOnPoiSearchListener(this);
            poiSearch.searchPOIAsyn();
        }
    }
    @ReactMethod
    public void reGeocodeSearch(final ReadableMap param)
    {
        double lat = param.getDouble("latitude");
        double lng = param.getDouble("longitude");
        LatLonPoint point = new LatLonPoint(lat, lng);
        RegeocodeQuery query = new RegeocodeQuery(point,200,GeocodeSearch.AMAP);

        GeocodeSearch  geo = new GeocodeSearch(this.reactContext);
        geo.setOnGeocodeSearchListener(this);
        geo.getFromLocationAsyn(query);
    }
    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
        //解析result获取地址描述信息
        if(rCode == 1000)
        {
            WritableMap map = Arguments.createMap();
            String city = result.getRegeocodeAddress().getCity();
            String district = result.getRegeocodeAddress().getDistrict();
            map.putString("city",city);
            map.putString("adcode",result.getRegeocodeAddress().getAdCode());
            map.putString("address",result.getRegeocodeAddress().getFormatAddress());
            map.putString("building",result.getRegeocodeAddress().getBuilding());
            map.putString("citycode",result.getRegeocodeAddress().getCityCode());
            map.putString("country",result.getRegeocodeAddress().getCountry());
            map.putString("district",district);
            map.putString("township",result.getRegeocodeAddress().getTownship());
            map.putString("province",result.getRegeocodeAddress().getProvince());
            if(result.getRegeocodeAddress().getPois().size() != 0){
                map.putString("name", result.getRegeocodeAddress().getPois().get(0).getTitle());
            }
            eventEmitter.emit("AMapReGeocodeSearch",map);
        }
        else{
            eventEmitter.emit("AMapReGeocodeSearch",null);
        }
    }
    @Override
    public void onGeocodeSearched(GeocodeResult result, int rCode) {

    }

    @ReactMethod
    public void showRoute(final ReadableMap param) {
   
        double slat = param.getDouble("slat");
        double slng = param.getDouble("slng");
        double dlat = param.getDouble("dlat");
        double dlng = param.getDouble("dlng");
        int queryType = param.getInt("queryType");
        RouteSearch routeSearch = new RouteSearch(this.reactContext);
        if(queryType == 1)
        {
            RouteSearch.RideRouteQuery query1 = new RouteSearch.RideRouteQuery(new RouteSearch.FromAndTo(new LatLonPoint(slat,slng),new LatLonPoint(dlat,dlng)));
            routeSearch.calculateRideRouteAsyn(query1);
        }
        else if(queryType == 2)
        {
            RouteSearch.WalkRouteQuery query1 = new RouteSearch.WalkRouteQuery(new RouteSearch.FromAndTo(new LatLonPoint(slat,slng),new LatLonPoint(dlat,dlng)));
            routeSearch.calculateWalkRouteAsyn(query1);
        }
        else
        {
            RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(
                    new RouteSearch.FromAndTo(new LatLonPoint(slat,slng),new LatLonPoint(dlat,dlng)), 10, null, null, "");
            routeSearch.calculateDriveRouteAsyn(query);
        }

        routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
            @Override
            public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

            }

            @Override
            public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
                System.out.println("DriveRouteResult : ");
                List<DriveStep> steps = driveRouteResult.getPaths().get(0).getSteps();
                StringBuilder builder = new StringBuilder();
                for(DriveStep s: steps)
                {
                   String poly  =   s.getPolyline().toString();
                   List<LatLonPoint> polyline = s.getPolyline();
                   for(LatLonPoint p :polyline) {
                       String pString = ""+p.getLongitude()+','+p.getLatitude();
                       builder.append(pString);
                       builder.append(";");
                   }
                }
                String polylines = builder.substring(0,builder.length()-1);
                WritableMap map = Arguments.createMap();
                map.putString("polylines",polylines);
                map.putDouble("distance",driveRouteResult.getPaths().get(0).getDistance());
                map.putDouble("duration",driveRouteResult.getPaths().get(0).getDuration());
                map.putInt("trafficlight",driveRouteResult.getPaths().get(0).getTotalTrafficlights());
                eventEmitter.emit("AMapRouteSearch",map);

            }

            @Override
            public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {
                List<WalkStep> steps = walkRouteResult.getPaths().get(0).getSteps();
                StringBuilder builder = new StringBuilder();
                for(WalkStep s: steps)
                {
                    String poly  =   s.getPolyline().toString();
                    List<LatLonPoint> polyline = s.getPolyline();
                    for(LatLonPoint p :polyline) {
                        String pString = ""+p.getLongitude()+','+p.getLatitude();
                        builder.append(pString);
                        builder.append(";");
                    }
                }
                String polylines = builder.substring(0,builder.length()-1);
                WritableMap map = Arguments.createMap();
                map.putString("polylines",polylines);
                map.putDouble("distance",walkRouteResult.getPaths().get(0).getDistance());
                map.putDouble("duration",walkRouteResult.getPaths().get(0).getDuration());

                eventEmitter.emit("AMapRouteSearch",map);
            }

            @Override
            public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
                List<RideStep> steps = rideRouteResult.getPaths().get(0).getSteps();
                StringBuilder builder = new StringBuilder();
                for(RideStep s: steps)
                {
                    String poly  =   s.getPolyline().toString();
                    List<LatLonPoint> polyline = s.getPolyline();
                    for(LatLonPoint p :polyline) {
                        String pString = ""+p.getLongitude()+','+p.getLatitude();
                        builder.append(pString);
                        builder.append(";");
                    }
                }
                String polylines = builder.substring(0,builder.length()-1);
                WritableMap map = Arguments.createMap();
                map.putString("polylines",polylines);
                map.putDouble("distance",rideRouteResult.getPaths().get(0).getDistance());
                map.putDouble("duration",rideRouteResult.getPaths().get(0).getDuration());
                eventEmitter.emit("AMapRouteSearch",map);
            }
        });
    }





















//    private ReadableMap toJSON(AMapLocation location) {
//        if (location == null) {
//            return null;
//        }
//        WritableMap map = Arguments.createMap();
//        map.putInt("errorCode", location.getErrorCode());
//        map.putString("errorInfo", location.getErrorInfo());
//        map.putString("locationDetail", location.getLocationDetail());
//        if (location.getErrorCode() == AMapLocation.LOCATION_SUCCESS) {
//            map.putDouble("timestamp", location.getTime());
//            map.putDouble("accuracy", location.getAccuracy());
//            map.putDouble("latitude", location.getLatitude());
//            map.putDouble("longitude", location.getLongitude());
//            map.putDouble("altitude", location.getAltitude());
//            map.putDouble("speed", location.getSpeed());
//            map.putDouble("heading", location.getBearing());
//            map.putInt("locationType", location.getLocationType());
//            map.putString("coordinateType", location.getCoordType());
//            map.putInt("gpsAccuracy", location.getGpsAccuracyStatus());
//            map.putInt("trustedLevel", location.getTrustedLevel());
//            if (!location.getAddress().isEmpty()) {
//                map.putString("address", location.getAddress());
//                map.putString("description", location.getDescription());
//                map.putString("poiName", location.getPoiName());
//                map.putString("country", location.getCountry());
//                map.putString("province", location.getProvince());
//                map.putString("city", location.getCity());
//                map.putString("cityCode", location.getCityCode());
//                map.putString("district", location.getDistrict());
//                map.putString("street", location.getStreet());
//                map.putString("streetNumber", location.getStreetNum());
//                map.putString("adCode", location.getAdCode());
//            }
//        }
//        return map;
//    }
}
